#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>//这脸你哥哥头文件时wait需要的
#include<sys/wait.h>
#include<stdlib.h>//exit()



//进程等待
//要释放僵尸进程的资源，僵尸进程 kill -9 也无法消灭
//僵尸进程占用系统资源，需要释放，而且要知道僵尸进程的工作完成的怎么样，索要要用到进程退出码

//再谈谈进程
//1.进程退出会变成僵尸  --- 会把自己的退出结构写入到自己到task_struct     ---与i出可以退出，但是你的数据一定要保存在pcb
//2.wait/waitpid 是一个系统调用 ---> OS -> OS有资格也有能力去读取子进程的task_struct

int main()
{
  pid_t id = fork();
  if(id == 0)
  {
    //子进程
    int cnt = 5;
    while(cnt)
    {
       printf("我是子进程: pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt--);
       sleep(1);
      // int*p = NULL//故意写个错误
       //*p = 100;
    }
    exit(10);//10秒后子进程退出
  }
  //父进程
 // sleep(15);
  int status = 0;//status不是被整体使用的，有自己的位图结构  --- 有32个bit位，我们关心前16位    ---- 0~7:终止信号(是否正常退出)   8~15:退出状态
  //pid_t ret = wait(NULL);//让父进程等待，回收子进程   ---- 返回的是子进程的id
  pid_t ret = waitpid(id,&status,0);//id:等待的id，&status:id的退出状态，0:阻塞式等待
  if(id > 0)
  {
    //这些宏能简化
    //是否正常退出
    if(WIFEXITED(status))// 若为正常终止子进程返回的状态，则为真。
    {
      //判断子进程运行结构是否ok
      printf("exit code:%d\n",WEXITSTATUS(status));
    }
    else
    {
      //....
      printf("child exit not normal!");
    }


    //按位操作太麻烦了
    //printf("wait success%d，sig number:%d,child exit code:%d\n",ret,(status & 0x7F),(status>>8) &0xFF);//7就是0111，F就是1111
  }//pcb  --->父进程会拿到子进程task_struct里面的退出信息
  return 0;
}
